package com.klangner.atarigo.model;

import java.util.Iterator;

import com.klangner.game.board.IBoard;
import com.klangner.game.board.IRuleChecker;
import com.klangner.game.board.Move;

public class AtariGoRules implements IRuleChecker {

	/**
	 * @see IRuleChecker#isLegalMove(Move)
	 */
	@Override
	public boolean isLegalMove(Move move, IBoard board) {

		Iterator<StonesGroup> it;
		
		
    // PASS always accepted
    if (move.isPass()) {
    	return true;
    }

    // Check coordinates
    if( move.getX() < 0 || move.getX() >= board.getSize() || 
    		move.getY() < 0 || move.getY() >= board.getSize())
    {
    	return false;
    }

    // Can't put on another stone
    if (board.getStone(move.getX(), move.getY()) != IBoard.NO_STONE)
    	return false;

    // if move has at least one free liberty, it's legal
    if( hasLiberties(move.getX(), move.getY(), board) )
    	return true;
    
    // Add stone to the board and check groups
    board.setStone(move.getX(), move.getY(), move.getColor());
    GroupingAlgorithm ga = new GroupingAlgorithm(board);
    
    // find opposite group without liberties
    it = ga.getGroups().iterator();
    while( it.hasNext() ){
    	StonesGroup group = it.next();
    	if(group.getLiberties().isEmpty() && group.getColor() != move.getColor()){
    		return true;
    	}
    }
    
    // check if this move is suicide
    it = ga.getGroups().iterator();
    while( it.hasNext() ){
    	StonesGroup group = it.next();
    	if(group.getLiberties().isEmpty() && group.getColor() == move.getColor()){
    		return false;
    	}
    }
    
    return true;
	}

	/**
	 * Count liberties for single stone
	 * @param x
	 * @param y
	 * @return true if has liberties
	 */
  private boolean hasLiberties(int x, int y, IBoard board) {
      
   	if( x > 0 && board.getStone(x-1, y) == IBoard.NO_STONE) 
  		return true;

    if( x < (board.getSize()-1) && board.getStone(x+1, y) == IBoard.NO_STONE)
    	return true;

   	if( y > 0 && board.getStone(x, y-1) == IBoard.NO_STONE) 
  		return true;

    if( y < (board.getSize()-1) && board.getStone(x, y+1) == IBoard.NO_STONE)
    	return true;

    return false;
  }



}
